package com.jjz.id.config;

import com.jjz.id.common.cipher.PasswordCipher;
import com.jjz.id.common.cipher.RsaCipher;
import com.jjz.id.common.password.RsaPasswordEncoder;
import com.jjz.id.config.properties.JueAuthorizationProperties;
import com.jjz.id.config.properties.JuePasswordProperties;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
import org.springframework.security.crypto.password.LdapShaPasswordEncoder;
import org.springframework.security.crypto.password.Md4PasswordEncoder;
import org.springframework.security.crypto.password.MessageDigestPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
import org.springframework.security.crypto.password.StandardPasswordEncoder;
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;

import java.util.HashMap;
import java.util.Map;

/**
 * @author ZJL
 * @create 2025-05-28-10:34
 */
@EnableConfigurationProperties({JuePasswordProperties.class})
@Configuration(
        proxyBeanMethods = false
)
public class PasswordConfiguration {
    private static final Logger log = LoggerFactory.getLogger(PasswordConfiguration.class);
    private static final String RSA_MODE = "rsa";
    @Bean
    public PasswordCipher passwordCipher(JuePasswordProperties securityPasswordSettings) {
        return new RsaCipher(securityPasswordSettings.getPrivateKey(), securityPasswordSettings.getPublicKey());
    }

    @Bean
    public PasswordEncoder passwordEncoder(PasswordCipher passwordCipher, JueAuthorizationProperties authorizationProperties) {
        String encodingId = StringUtils.isNotEmpty(authorizationProperties.getPasswordEncoder()) ? authorizationProperties.getPasswordEncoder() : "bcrypt";
        Map<String, PasswordEncoder> encoders = new HashMap();
        encoders.put("bcrypt", new BCryptPasswordEncoder());
        encoders.put("ldap", new LdapShaPasswordEncoder());
        encoders.put("MD4", new Md4PasswordEncoder());
        encoders.put("MD5", new MessageDigestPasswordEncoder("MD5"));
        encoders.put("noop", NoOpPasswordEncoder.getInstance());
        encoders.put("pbkdf2", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_5());
        encoders.put("pbkdf2@SpringSecurity_v5_8", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8());
        encoders.put("scrypt", SCryptPasswordEncoder.defaultsForSpringSecurity_v4_1());
        encoders.put("scrypt@SpringSecurity_v5_8", SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8());
        encoders.put("SHA-1", new MessageDigestPasswordEncoder("SHA-1"));
        encoders.put("SHA-256", new MessageDigestPasswordEncoder("SHA-256"));
        encoders.put("sha256", new StandardPasswordEncoder());
        encoders.put("argon2", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_2());
        encoders.put("argon2@SpringSecurity_v5_8", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8());
        if (passwordCipher != null && passwordCipher instanceof RsaCipher) {
            encoders.put("rsa", new RsaPasswordEncoder((RsaCipher)passwordCipher));
            if ("rsa".equals(authorizationProperties.getPasswordEncoder())) {
                encodingId = "rsa";
            }
        }

        log.info("the current password encoder is using : " + encodingId + " as default");
        return new DelegatingPasswordEncoder(encodingId, encoders);
    }
}
